package config

import (
	"fmt"
	"os"
	"time"
)

// Watch 观察者，监听配置文件的变化，并调用
func Watch(filename string, listener Listener) (*Configuration, error) {
	// 这个函数在会根据文件的保存来触发监听循环
	// 首先创建初始状态
	initState, err := os.Stat(filename)
	if err != nil {
		return nil, err
	}
	// fmt.Println("inistate ok")
	// 首先第一次parse
	oldConf, err := NewConfiguration(filename)
	if err != nil {
		//初始parse出错
		// 比较友好的选择是在屏幕输出提示信息表示现在初始文件格式不正确
		// 但不能直接返回
		fmt.Println(err)
	}
	// fmt.Println("oldstate ok")
	var newConf *Configuration

	for {
		// 一个简单的循环，根据保存文件来触发监听
		// 监听自主选择是否退出
		state, err := os.Stat(filename)
		if err != nil {
			return nil, nil
		}

		if state.ModTime() == initState.ModTime() {
			// 如果没保存，不会触发listen，同时更新状态
			fmt.Println("waiting fix and sleep")
			time.Sleep(1 * time.Second)
			continue
		}
		// fmt.Println("out there")
		initState = state

		// 尝试parse文件
		newConf, err = NewConfiguration(filename)
		if err != nil {
			fmt.Println(err)
		}

		out := listener.Listen(oldConf, newConf)

		if out {
			fmt.Println("listener want to exit")
			// 这是由用户自定义行为
			break
		}
	}
	// 至于是否阻塞，还是需要
	return newConf, nil
}

// WatcherRoutine 一个监听文件变化直到符合listener结束要求的go程
func WatcherRoutine(filename string, listener Listener) (*Configuration, error) {
	var conf *Configuration = nil
	var err error = nil
	doneChan := make(chan bool)
	go func(doneChan chan bool) {
		defer func() {
			doneChan <- true
		}()
		conf, err = Watch(filename, listener)
		if err != nil {
			fmt.Println(err)
		}
	}(doneChan)
	<-doneChan
	return conf, err
}
